home *** CD-ROM | disk | FTP | other *** search
- char *vers = "copytape version 1.2, 15 May 87";
-
- /* copytape -- tape-to-tape copy program */
- /*
- /* F. da Cruz, Columbia University Center for Computing Activities, May 1987 */
- /*
- /* Parts cribbed from Jim Guyton's readtape and writetape programs, and */
- /* from ansitar. If run with debug printout, output tape is slightly /*
- /* longer than input tape. */
-
- /* Suggested minor improvements: check that input & output devices are */
- /* really tapes. Really check that input & output tape not same device. */
- /* Add some statistics. Use dynamic buffers & pointers, rather than fixed, */
- /* to save space. Etc. */
-
- /* Includes */
-
- #include <stdio.h> /* standard i/o */
- #include <sys/types.h> /* data types needed by below */
- #include <sys/mtio.h> /* magtape i/o */
- #include <sys/ioctl.h> /* i/o control */
-
- /* I/O descriptors, flags, etc. */
-
- int in, out; /* input, output tapes */
- int teof; /* input tape eof flag */
- int debug = 0, dv = 0; /* command line option flags */
- long copyfile(); /* forward dcl of non-int function */
-
- /* Tape stuff */
-
- char *indef = "/dev/rmt12"; /* default input drive */
- char *outdef = "/dev/rmt13"; /* default output drive */
- char *intape = "";
- char *outape = "";
- struct mtop mtx; /* tape i/o structure for ioctl */
-
- /* Buffer stuff */
-
- #define BLKSIZE 30*1024 /* I/O buffer size */
- #define BLOCKS 10 /* Number of buffers */
- int maxblock = BLKSIZE;
- char buf[BLOCKS][BLKSIZE]; /* Declare buffer array */
- int buflen[BLOCKS]; /* & array of data lengths per buf */
-
- char errbuf[100]; /* Buffer for making error strings */
-
- /* Main program */
-
- main(argc,argv) int argc; char *argv[]; {
-
- long ct, files, bytes = 0L;
- int filenum = 1;
- char x, *xp;
-
- while (--argc > 0) { /* Parse options */
- argv++;
- if (**argv == '-') {
- x = *(*argv+1); /* Option letter */
- xp = *argv+1; /* Point past dash */
- while (x) { /* Loop thru bundled options */
- switch(x) {
- case 'd': /* Debugging display */
- debug = 1;
- break;
- case 'f': /* From device */
- if (*(xp+1)) fatal("Invalid argument bundling");
- intape = *++argv;
- argc--;
- if (*intape == '-' || argc <= 0)
- fatal("-f argument missing");
- break;
- case 't': /* To device */
- if (*(xp+1)) fatal("Invalid argument bundling");
- outape = *++argv;
- argc--;
- if (*outape == '-' || argc <= 0)
- fatal("-t argument missing");
- break;
- case 'v': /* Version info */
- dv = 1;
- break;
- default : usage();
- }
- x = *++xp; /* See if options are bundled */
- }
- } else usage();
- }
- if (debug || dv) { /* Display version info if asked */
- fprintf(stderr,"%s\n",vers);
- fprintf(stderr,"%d buffers, %d bytes each\n\n",BLOCKS,maxblock);
- }
-
- if (!*intape) intape = indef; /* Supply defaults */
- if (!*outape) outape = outdef;
- if (strcmp(intape,"0") == 0) intape = indef;
- if (strcmp(intape,"1") == 0) intape = outdef;
- if (strcmp(outape,"0") == 0) outape = indef;
- if (strcmp(outape,"1") == 0) outape = outdef;
- if (strcmp(outape,intape) == 0) {
- fprintf(stderr,"You must specify two different tape drives\n");
- exit(1);
- }
- if (debug) {
- fprintf(stderr,"input drive: %s\n",intape);
- fprintf(stderr,"output drive: %s\n",outape);
- }
- in = open(intape, 0); /* Open input tape */
- if (in > 0)
- printf("Reading from tape '%s'\n", intape);
- else {
- sprintf(errbuf,"Can't open tape %s for reading",intape);
- fatal(errbuf);
- }
- if (rew(in) < 0) /* Rewind to load point */
- fatal("Can't rewind input tape");
-
- out = open(outape, 1); /* Open output tape */
- if (out > 0)
- printf("Writing to tape '%s'\n", outape);
- else {
- sprintf(errbuf,"Can't open tape %s for writing",outape);
- fatal(errbuf);
- }
- if (rew(out) < 0) /* Rewind to load point */
- fatal("Can't rewind output tape");
-
- system("date"); /* Say when starting */
- ct = files = 1; /* Initialize counters */
- while (ct) { /* Copy each file on tape */
- if (debug) fprintf(stderr,"\nfile %ld:", files);
- ct = copyfile(); /* Copy the file */
- files++; /* Count the file */
- bytes += ct; /* Accumulate total byte count */
- }
- tapemark(out); /* Write final tapemark */
- close(out); /* Close tape drives */
- close(in);
- system("date"); /* When done, print messages */
- printf("\nDone, copied %ld bytes in %ld file(s)\n", bytes, (files - 1));
- exit(0);
- }
-
- long /* Copy a file from in to out */
- copyfile() { /* Returns number of bytes read */
-
- int i, blks; /* Loop control, block count */
- long ct = 0; /* Character count */
-
- teof = 0; /* Copy tape blocks till tape eof */
- /* Do several buffers at a time */
- while (!teof) {
-
- for (blks = i = 0; i < BLOCKS; i++) { /* Read some buffers */
-
- if ((buflen[i] = read(in, buf[i], BLKSIZE)) < 0)
- fatal("I/O error reading tape");
- else if (buflen[i] > 0) {
- blks++; /* Count this block */
- if (debug) fprintf(stderr," %d:%d",i,buflen[i]);
- } else { /* Count of 0 means end of tape file */
- if (debug) fprintf(stderr," eof");
- teof = 1; /* Flag tape file eof. */
- break;
- }
- }
- if (debug) fprintf(stderr," [%d]",blks); /* # of blocks read */
-
- for (i = 0; i < blks; i++) { /* Write out the buffers. */
-
- if (debug) fprintf(stderr," w%d:%d",i,buflen[i]);
- if (write(out, buf[i], buflen[i]) != buflen[i])
- fatal("Write error");
- ct += buflen[i]; /* Keep track of # of bytes written */
- buflen[i] = 0;
- }
- }
- if (debug) fprintf(stderr," tm");
- if (tapemark(out) < 0) /* Write file mark. */
- fatal("Can't write tape mark");
- return(ct); /* Return output byte count. */
- }
-
- tapemark(tf) int tf; { /* Write a tapemark (file mark) */
- mtx.mt_count = 1;
- mtx.mt_op = MTWEOF;
- return(ioctl(tf, MTIOCTOP, (char *) &mtx));
- }
-
- rew(tf) int tf; { /* Rewind tape */
- mtx.mt_op = MTREW;
- return(ioctl(tf, MTIOCTOP, (char *) &mtx));
- }
-
- fatal(s) char *s; { /* Fatal error message and exit */
- perror(s); /* Include last system error */
- exit(1);
- }
-
- usage() {
- fprintf(stderr,"usage: copytape [-d -v -f intape -t outtape]\n");
- fprintf(stderr,"-d=debug, -v=version, -f=from, -t=to\n");
- fprintf(stderr,"intape default %s, outtape default %s\n",indef,outdef);
- fprintf(stderr,"maximum blocksize: %ld.\n",maxblock);
- fprintf(stderr,"number of blocks buffered: %d.\n",BLOCKS);
- exit(1);
- }
-